/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#ifndef RELSEQUENCE_H
#define RELSEQUENCE_H
/* -*-C++-*-
******************************************************************************
*
* File:         RelSequence.h
* Description:  Class definitions for the classes RelSequence
*               and PhysSequence
* Created:      6/17/97
* Language:     C++
*
*
*
*
******************************************************************************
*/

#include "RelExpr.h"

// forward references

class Generator;
class MapTable;
class Attributes;

// Class RelSequence
// --------------------------------------------------------

// The RelSequence RelExpr is the logical RelExpr used to implement the
// "sequence by clause" and is introduced by the parser.  The physical
// version of this node is the RelExpr class PhysSequence.  The data
// members of this class are:
//
// ItemExpr *requiredOrderTree_ : An ItemExpr list of columns
// representing the reqired sort order for this node.  A required sort
// order is specified withg th sort by clause.
//
// ValueIdList requiredOrder_ : The bound version of
// requiredOrderTree_.
//
// ValueIdSet sequenceFunctions_ : A set of all the sequence
// functions associated with this RelSequence node.  They are gathered
// and assigned to the RelSequence node during binding.
//
class RelSequence : public RelExpr
{
public:

  // The constructor
  //
  RelSequence(RelExpr *child = NULL,
              ItemExpr *requiredOrder = NULL,
              CollHeap *oHeap = CmpCommon::statementHeap());

  RelSequence(RelExpr *child,
              ItemExpr *partitionBy,
              ItemExpr *orderBy,
              CollHeap *oHeap = CmpCommon::statementHeap());

  // The destructor
  //
  virtual ~RelSequence();

  // RelSequence has one child.
  //
  virtual Int32 getArity() const {return 1;};

  //++MV
  void addRequiredOrderTree(ItemExpr *orderExpr);

  // a virtual function for performing name binding within the query tree
  //
  RelExpr * bindNode(BindWA *bindWAPtr);

  // Each operator supports a (virtual) method for transforming its
  // scalar expressions to a canonical form
  //
  virtual void transformNode(NormWA & normWARef,
			     ExprGroupId & locationOfPointerToMe);

  // a method used during subquery transformation for pulling up predicates
  // towards the root of the transformed subquery tree
  //
  // RelSequence cannot pull up any preds. so redefine this method.
  //
  virtual void pullUpPreds();

  // a method used for recomputing the outer references (external dataflow
  // input values) that are still referenced by each operator in the
  // subquery tree after the predicate pull up is complete.
  //
  virtual void recomputeOuterReferences();

  // Each operator supports a (virtual) method for rewriting its
  // value expressions.
  //
  virtual void rewriteNode(NormWA & normWARef);

  // Each operator supports a (virtual) method for performing
  // predicate pushdown and computing a "minimal" set of
  // characteristic input and characteristic output values.
  //
  virtual RelExpr * normalizeNode(NormWA & normWARef);

  // Method to push down predicates from a RelSequence node into the
  // children
  //
  virtual
  void pushdownCoveredExpr(const ValueIdSet & outputExprOnOperator,
                           const ValueIdSet & newExternalInputs,
                           ValueIdSet& predOnOperator,
			   const ValueIdSet * nonPredExprOnOperator = NULL,
                           Lng32 childId = (-MAX_REL_ARITY) );

  // Return a the set of potential output values of this node.
  // For RelSequence, this is the output of the child, plus all
  // the values generated by RelSequence
  //
  virtual void getPotentialOutputValues(ValueIdSet &vs) const;

  // add all the expressions that are local to this
  // node to an existing list of expressions (used by GUI tool and Explain)
  //
  virtual void addLocalExpr(LIST(ExprNode *) &xlist,
			    LIST(NAString) &llist) const;

  // Compute a hash value for a chain of derived RelExpr nodes.
  // Used by the Cascade engine as a quick way to determine if
  // two nodes are identical.
  // Can produce false positives, but should not produce false
  // negatives.
  //
  virtual HashValue topHash();

  // A more thorough method to compare two RelExpr nodes.
  // Used by the Cascades engine.
  //
  virtual NABoolean duplicateMatch(const RelExpr & other) const;

  // Copy a chain of derived nodes (Calls RelExpr::copyTopNode).
  // Needs to copy all relevant fields.
  // Used by the Cascades engine.
  //
  virtual RelExpr *copyTopNode(RelExpr *derivedNode = NULL,
			       CollHeap *outHeap = NULL);

  // synthesize logical properties
  //
  virtual void synthLogProp(NormWA * normWAPtr = NULL);
  virtual void synthEstLogProp(const EstLogPropSharedPtr& inputEstLogProp);

  virtual Context* createContextForAChild(Context* myContext,
                                          PlanWorkSpace* pws,
                                          Lng32& childIndex);

  // get a printable string that identifies the operator
  //
  virtual const NAString getText() const {return "Sequence";};

  inline void setCancelExprTree(ItemExpr *expr)
  { cancelExprTree_ = expr; }

  ValueIdList mapSortKey(const ValueIdList &sortKey) const;

  // Accessor methods
  inline const ValueIdList & requiredOrder() const { return requiredOrder_; }

  inline const ValueIdList & partition() const { return partition_; }

  inline const ValueIdSet & sequenceFunctions() const
  { return sequenceFunctions_; }

  inline const ValueIdSet & returnSeqFunctions() const
  { 
    return returnSeqFunctions_; 
  }
  inline const ValueIdSet & movePartIdsExpr() const
  { 
    return movePartIdsExpr_; 
  }
  inline const ValueIdSet & sequencedColumns() const
  { return sequencedColumns_; }

  inline void addSequencedColumn(ValueId col)
  { sequencedColumns_ += col; }

  inline const ValueIdList & cancelExpr() const
  { return cancelExpr_; }

  // Add unresolved sequence functions to the RelSequence operator
  // found when binding the select list.  Also, if OLAP, bind the
  // partition by and order by clauses and add to RelSequence.
  //
  void addUnResolvedSeqFunctions(ValueIdSet &unresolvedSeqFuncs,
                                 BindWA *bindWA);

   inline void setRequiredOrder(const ValueIdList &reqOrder)
   { requiredOrder_ = reqOrder; }

   inline void setPartition(const ValueIdList &partition)
   { partition_ = partition; }

   ValueIdList getPartitionChange() { return partitionChange_ ;}

   ItemExpr * getPartitionBy() { return partitionBy_;}

   void setPartitionBy(ItemExpr * part) {partitionBy_ = part;}

   inline void setSequenceFunctions(const ValueIdSet &seqFuncs)
   { sequenceFunctions_ = seqFuncs; }

  inline void setSequencedColumns(const ValueIdSet &seqCols)
  { sequencedColumns_ = seqCols; }

  inline void setCancelExpr(const ValueIdList &expr)
  { cancelExpr_ = expr; }

  inline void setHasOlapFunctions(const NABoolean v)
  { hasOlapFunctions_ = v; }
  inline const NABoolean getHasOlapFunctions() const
  { return hasOlapFunctions_; }

  inline void setHasTDFunctions(const NABoolean v)
  { hasTDFunctions_ = v; }
  inline const NABoolean getHasTDFunctions() const
  { return hasTDFunctions_; }

  ItemExpr * getRequiredOrderTree() {return requiredOrderTree_;}

  Lng32 getCachedNumHistoryRows()
  {
    return cachedNumHistoryRows_;
  }
  void setCachedNumHistoryRows( Lng32 v)
  {
    cachedNumHistoryRows_ = v;
  }

  NABoolean getCachedUnboundedFollowing()
  {
    return cachedUnboundedFollowing_;
  }
  void setCachedUnboundedFollowing( NABoolean v)
  {
    cachedUnboundedFollowing_ = v;
  }

  Lng32 getCachedMinFollowingRows()
  {
    return cachedMinFollowingRows_;
  }
  void setCachedMinFollowingRows( Lng32 v)
  {
    cachedMinFollowingRows_ = v;
  }

  Lng32 getCachedHistoryRowLength()
  {
    return cachedHistoryRowLength_;
  }
  void setCachedHistoryRowLength( Lng32 v)
  {
    cachedHistoryRowLength_ = v;
  }

  NABoolean getHistoryInfoCached()
  {
    return historyInfoCached_;
  }
  void setHistoryInfoCached( NABoolean v)
  {
    historyInfoCached_ = v;
  }
  
protected:

  inline ValueIdList & requiredOrder() { return requiredOrder_; }

  inline ValueIdList & partition() { return partition_; }

  inline ValueIdSet & sequenceFunctions() { return sequenceFunctions_; }

  inline ValueIdSet & readSeqFunctions() { return sequenceFunctions_; }
  inline ValueIdSet & returnSeqFunctions() { return returnSeqFunctions_; }
  inline ValueIdSet & sequencedColumns() { return sequencedColumns_; }

  inline ValueIdList & cancelExpr() { return cancelExpr_; }

  void addCancelExpr(CollHeap *wHeap);
  
  inline ValueIdSet & checkPartitionChangeExpr() { return checkPartitionChangeExpr_; }
  inline ValueIdSet & movePartIdsExpr() { return movePartIdsExpr_; }

private:
  // Return a pointer to the required order tree after
  // setting it to NULL.
  //
  ItemExpr *removeRequiredOrderTree();

  // An ItemExpr list of columns representing the reqired sort order
  // for this node.
  //
  ItemExpr *requiredOrderTree_;

  // The ItemExpr list of columns representing the partition by clause.
  //
  ItemExpr *partitionBy_;

  // -- MV
  // During execution, when the cancelExpr evaluates to TRUE, the Sequence
  // node cancels the parent request.
  ItemExpr *cancelExprTree_;

  // The bound version of requiredOrderTree_.
  //
  ValueIdList requiredOrder_;

    // The bound version of partitionByTree_
  //
  ValueIdList partition_;

  ValueIdList partitionChange_;
  // A set of all the sequence functions associated with this
  // RelSequence node.  They are gathered and assigned to the
  // RelSequence node during binding.
  //
  ValueIdSet sequenceFunctions_;

  ValueIdSet returnSeqFunctions_;
  ValueIdSet sequencedColumns_;

  // -- MV
  ValueIdList cancelExpr_;

  // flag that defines whether this RelSequence was created for TD functions
  // or not
  NABoolean hasTDFunctions_;
  NABoolean hasOlapFunctions_;

  ValueIdSet checkPartitionChangeExpr_;
  ValueIdSet movePartIdsExpr_;

  //cached parameters
  NABoolean historyInfoCached_;
  Lng32 cachedNumHistoryRows_;
  NABoolean cachedUnboundedFollowing_;
  Lng32 cachedMinFollowingRows_;
  Lng32 cachedHistoryRowLength_;

}; // class RelSequence

// Class PhysSequence ----------------------------------------------------
// The PhysSequence node replaces the logical RelSequence node through the
// application of the PhysSequenceRule. This transformation is
// designed to present a purely physical verison of this operator
// that is both a logical and physical node. The PhysSequence node
// does not add any data members. It adds a few virtual methods.
// -----------------------------------------------------------------------
class PhysSequence : public RelSequence
{
public:

  // The constructor
  //
  PhysSequence(RelExpr *child = NULL,
                      CollHeap *oHeap = CmpCommon::statementHeap())
    : RelSequence(child, NULL, oHeap)
  {
    numHistoryRows_ = getDefault(DEF_MAX_HISTORY_ROWS);
    minFixedHistoryRows_ = 0;
    unboundedFollowing_ = FALSE;
    minFollowingRows_ = 0;
  };

  // The destructor.
  //
  virtual ~PhysSequence();

  // methods to do code generation of the physical node.
  //
  virtual RelExpr * preCodeGen(Generator * generator,
			       const ValueIdSet & externalInputs,
			       ValueIdSet &pulledNewInputs);
  virtual short codeGen(Generator*);

  // generate CONTROL QUERY SHAPE fragment for this node.
  //
  virtual short generateShape(CollHeap * space, char * buf, NAString * shapeStr = NULL);

  // Copy a chain of derived nodes (Calls RelSequence::copyTopNode).
  // Needs to copy all relevant fields (in this case no fields
  // need to be copied)
  // Used by the Cascades engine.
  //
  virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL,
				CollHeap *outHeap = NULL);

  // cost functions
  //
  virtual PhysicalProperty *synthPhysicalProperty(const Context *context,
                                                  const Lng32 planNumber,
                                                  PlanWorkSpace  *pws);
  virtual CostMethod* costMethod() const;

  // The method gets redefined since Sequnece may be a BMO depending
  // on its inputs.
  virtual NABoolean isBigMemoryOperator(const Context* context,
                                        const Lng32 planNumber);

  virtual CostScalar getEstimatedRunTimeMemoryUsage(Generator *generator, NABoolean perNode, Lng32 *numStreams = NULL);

  // Redefine these virtual methods to declare this node as a
  // physical node.
  //
  virtual NABoolean isLogical() const {return FALSE;};
  virtual NABoolean isPhysical() const {return TRUE;};

  ExplainTuple *addSpecificExplainInfo(ExplainTupleMaster *explainTuple,
					      ComTdb * tdb,
					      Generator *generator);

  // Helper function that traverses the set of root sequence functions
  // supplied by the compiler and constructs the set of all of the
  // attributes that must be materialized in the history row.
  //
  void getHistoryAttributes(const ValueIdSet &sequenceFunctions,
                            const ValueIdSet &outputFromChild,
                            ValueIdSet &historyAttributes,
                            NABoolean addConvNodes = FALSE,
                            CollHeap *wHeap = NULL,
                            ValueIdMap *origAttributes = NULL) const;

  // Helper function to compute the attribute for the history buffer
  // based on the items projected from the child and the computed
  // history items.  Also, adds the attribute information the the map
  // table.
  //
  void computeHistoryAttributes(Generator *generator,
                                MapTable *localMapTable,
                                Attributes **attrs,
                                const ValueIdSet &historyIds) const;

  // Helper function that traverses the set of root sequence functions
  // supplied by the compiler and dynamically determines the size
  // of the history buffer.
  //
  void computeHistoryRows(const ValueIdSet &sequenceFunctions,
                          Lng32 &computedHistoryRows,
                          Lng32 &unableToCalculate,
                          //long &minFixedHistoryRows,
                          NABoolean &unboundedFollowing, //&unlimitedHistoryRows,
                          Lng32 &minFollowingRows,
                          const ValueIdSet &outputFromChild);


  // Return a READ-ONLY reference to the number of history rows to be
  // allocated in the history buffer.
  //
  inline const Lng32 & numHistoryRows() const { return numHistoryRows_; }

  // Set the number of history rows to be allowed in the history buffer.
  void setNumHistoryRows(Lng32 numHistoryRows);

  void setUnboundedFollowing(NABoolean v);
  NABoolean getUnboundedFollowing() const ;

  void setMinFollowingRows(Lng32 v);

  // set the min following rows to max(v, minFollowingRows_);
  void computeAndSetMinFollowingRows(Lng32 v);

  Lng32 getMinFollowingRows() const ;

  Lng32 getEstHistoryRowLength() const
  {
    return estHistoryRowLength_;
  }

  void setEstHistoryRowLength(Lng32 v)
  {
    estHistoryRowLength_ = v;
  }

  void updateEstHistoryRowLength(ValueIdSet &histIds,
				ValueId newValId,
                                Lng32 &estimatedLength)
  {
    if (!histIds.contains(newValId))
    {
      estimatedLength += newValId.getType().getTotalSize();
      histIds += newValId;
    }
  }

  void seperateReadAndReturnItems(CollHeap *wHeap);

  void computeReadNReturnItems(ValueId seqVid,
                               ValueId vid,
                               const ValueIdSet &outputFromChild,
                               CollHeap *wHeap);
  
  void transformOlapFunctions(CollHeap *wHeap);

  void computeHistoryParams( Lng32 histRecLength,
                             Lng32 &maxRowsInOLAPBuffer,
                             Lng32 &minNumberOfOLAPBuffers,
                             Lng32 &numberOfWinOLAPBuffers,
                             Lng32 &maxNumberOfOLAPBuffers,
                             Lng32 &olapBufferSize);

  void retrieveCachedHistoryInfo(RelSequence * cacheRelSeq) ;


  void estimateHistoryRowLength(const ValueIdSet &sequenceFunctions,
                                const ValueIdSet &outputFromChild,
                                ValueIdSet &histIds,
                                Lng32 &estimatedLength);

  void addCheckPartitionChangeExpr( Generator *generator,
                                    NABoolean addConvNodes = FALSE,
                                    ValueIdMap *origAttributes = NULL);
private:

  // The number of history rows to allocate for the history buffer.
  // Is initialized to the value of the default REF_MAX_HISTORY_ROWS.
  // Later it may be reduced if it can be determined that fewer rows
  // can safely be used.
  //
  Lng32 numHistoryRows_;

  // minimum number of rows that need to fit in the history buffer
  // unbounded to Bounded and bounded to bounded cases
  // if there is an unbounded following we still need to detremine the size for above cases
  Lng32 minFixedHistoryRows_;

  // do need to have unlimited size-- unbounded following cases
  NABoolean unboundedFollowing_; //unlimitedHistoryRows_;


  Lng32 minFollowingRows_;

  //estimated history row length
  Lng32 estHistoryRowLength_;

}; // class PhysSequence

#endif
